#include "usart.h"
#include "dma.h"

//如果一次接收的数据超过了rxbuf的总大小，就会处理不到完整数据

mUart_t mUart[4]={0};
mUart5_t mUart5={0};

UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_uart4_rx;
DMA_HandleTypeDef hdma_uart4_tx;
DMA_HandleTypeDef hdma_usart1_rx;
DMA_HandleTypeDef hdma_usart1_tx;
DMA_HandleTypeDef hdma_usart2_rx;
DMA_HandleTypeDef hdma_usart2_tx;
DMA_HandleTypeDef hdma_usart3_rx;
DMA_HandleTypeDef hdma_usart3_tx;

void uart_tx_write_to_queue(u8 n,u8 *buf,u16 len);
void uart_rx_write_to_queue(u8 n,u16 first,u16 last);

//调试口配置
int fputc(int ch, FILE * p_file)
{
	u8 data=ch;
	uart2_send_no_queue(&data,1);
    return ch;
}

//初始化时赋值给函数指针
static u8 uart1_get_tc(void)
{
	return __HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)==0?0:1;
}
static u8 uart2_get_tc(void)
{
	return __HAL_UART_GET_FLAG(&huart2,UART_FLAG_TC)==0?0:1;
}
static u8 uart3_get_tc(void)
{
	return __HAL_UART_GET_FLAG(&huart3,UART_FLAG_TC)==0?0:1;
}
static u8 uart4_get_tc(void)
{
	return __HAL_UART_GET_FLAG(&huart4,UART_FLAG_TC)==0?0:1;
}
static void uart1_clear_tc(void)
{
	__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TC);
}
static void uart2_clear_tc(void)
{
	__HAL_UART_CLEAR_FLAG(&huart2,UART_FLAG_TC);
}
static void uart3_clear_tc(void)
{
	__HAL_UART_CLEAR_FLAG(&huart3,UART_FLAG_TC);
}
static void uart4_clear_tc(void)
{
	__HAL_UART_CLEAR_FLAG(&huart4,UART_FLAG_TC);
}

void my_uart1_init(void)
{
	huart1.Instance = USART1;
	huart1.Init.BaudRate = UART1_BAUD;
	huart1.Init.WordLength = UART_WORDLENGTH_8B;
	huart1.Init.StopBits = UART_STOPBITS_1;
	huart1.Init.Parity = UART_PARITY_NONE;
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	if(HAL_UART_Init(&huart1)!=HAL_OK)	MY_LOG("error");
	__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 	//使能IDLE中断
	SET_BIT(huart1.Instance->CR3, USART_CR3_DMAR);	//使能串口DMA收发	
	SET_BIT(huart1.Instance->CR3, USART_CR3_DMAT);
	
	hdma_usart1_rx.Instance = DMA1_Channel5;
	hdma_usart1_tx.Instance = DMA1_Channel4;
	dma_rx_init(hdma_usart1_rx.Instance,(u32)&huart1.Instance->DR,(u32)mUart[0].rxbuf,UART_RX_QBUFLEN);
	
	mUart[0].clear_tc=uart1_clear_tc;
	mUart[0].get_tc=uart1_get_tc;
	mUart[0].rxcallback=uart1_send;
}

void my_uart2_init(void)
{
	huart2.Instance = USART2;
	huart2.Init.BaudRate = UART2_BAUD;
	huart2.Init.WordLength = UART_WORDLENGTH_8B;
	huart2.Init.StopBits = UART_STOPBITS_1;
	huart2.Init.Parity = UART_PARITY_NONE;
	huart2.Init.Mode = UART_MODE_TX_RX;
	huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart2.Init.OverSampling = UART_OVERSAMPLING_16;
	if(HAL_UART_Init(&huart2)!=HAL_OK)	MY_LOG("error");
	__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); //使能IDLE中断
	SET_BIT(huart2.Instance->CR3, USART_CR3_DMAR);
	SET_BIT(huart2.Instance->CR3, USART_CR3_DMAT);
	
	hdma_usart2_rx.Instance = DMA1_Channel6;
	hdma_usart2_tx.Instance = DMA1_Channel7;
	dma_rx_init(hdma_usart2_rx.Instance,(u32)&huart2.Instance->DR,(u32)mUart[1].rxbuf,UART_RX_QBUFLEN);	//开始接收
	
	mUart[1].clear_tc=uart2_clear_tc;
	mUart[1].get_tc=uart2_get_tc;
	mUart[1].rxcallback=uart2_send;
}
void my_uart3_init(void)
{
	huart3.Instance = USART3;
	huart3.Init.BaudRate = UART3_BAUD;
	huart3.Init.WordLength = UART_WORDLENGTH_8B;
	huart3.Init.StopBits = UART_STOPBITS_1;
	huart3.Init.Parity = UART_PARITY_NONE;
	huart3.Init.Mode = UART_MODE_TX_RX;
	huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart3.Init.OverSampling = UART_OVERSAMPLING_16;
	if(HAL_UART_Init(&huart3)!=HAL_OK)	MY_LOG("error");
	__HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //使能IDLE中断
	SET_BIT(huart3.Instance->CR3, USART_CR3_DMAR);
	SET_BIT(huart3.Instance->CR3, USART_CR3_DMAT);
	
	hdma_usart3_rx.Instance = DMA1_Channel3;
	hdma_usart3_tx.Instance = DMA1_Channel2;
	dma_rx_init(hdma_usart3_rx.Instance,(u32)&huart3.Instance->DR,(u32)mUart[2].rxbuf,UART_RX_QBUFLEN);	//开始接收
	
	mUart[2].clear_tc=uart3_clear_tc;
	mUart[2].get_tc=uart3_get_tc;
	mUart[2].rxcallback=uart3_send;
}

void my_uart4_init(void)
{
	huart4.Instance = UART4;
	huart4.Init.BaudRate = UART4_BAUD;
	huart4.Init.WordLength = UART_WORDLENGTH_8B;
	huart4.Init.StopBits = UART_STOPBITS_1;
	huart4.Init.Parity = UART_PARITY_NONE;
	huart4.Init.Mode = UART_MODE_TX_RX;
	huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart4.Init.OverSampling = UART_OVERSAMPLING_16;
	if(HAL_UART_Init(&huart4)!=HAL_OK)	MY_LOG("error");
	__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE); //使能IDLE中断
	SET_BIT(huart4.Instance->CR3, USART_CR3_DMAR);
	SET_BIT(huart4.Instance->CR3, USART_CR3_DMAT);
	
	hdma_uart4_rx.Instance = DMA2_Channel3;
	hdma_uart4_tx.Instance = DMA2_Channel5;
	dma_rx_init(hdma_uart4_rx.Instance,(u32)&huart4.Instance->DR,(u32)mUart[3].rxbuf,UART_RX_QBUFLEN);	//开始接收
	
	mUart[3].clear_tc=uart4_clear_tc;
	mUart[3].get_tc=uart4_get_tc;
	mUart[3].rxcallback=uart4_send;
}

void my_uart5_init(void)
{
	huart5.Instance = UART5;
	huart5.Init.BaudRate = UART5_BAUD;
	huart5.Init.WordLength = UART_WORDLENGTH_8B;
	huart5.Init.StopBits = UART_STOPBITS_1;
	huart5.Init.Parity = UART_PARITY_NONE;
	huart5.Init.Mode = UART_MODE_TX_RX;
	huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart5.Init.OverSampling = UART_OVERSAMPLING_16;
	if(HAL_UART_Init(&huart5)!=HAL_OK)	MY_LOG("error");
	__HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE); //使能rxne中断
	mUart5.rxcallback=uart5_send;
}

//5个串口发送
void uart1_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(0,buf,len);
}
void uart2_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(1,buf,len);
}
void uart3_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(2,buf,len);
}
void uart4_send(u8 *buf,u16 len)
{
	uart_tx_write_to_queue(3,buf,len);
}
void uart5_send(u8 *buf,u16 len)			//串口5没有dma通道
{
	while(len--){
		huart5.Instance->DR=*buf++;
		while(__HAL_UART_GET_FLAG(&huart5,UART_FLAG_TC)==0);
	}
}
void uart1_send_no_queue(u8 *buf,u16 len)	//直接写寄存器，特殊情况使用
{
	while(len--){
		huart1.Instance->DR=*buf++;
		while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)==0);
	}
}
void uart2_send_no_queue(u8 *buf,u16 len)	//直接写寄存器，特殊情况使用
{
	while(len--){
		huart2.Instance->DR=*buf++;
		while(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_TC)==0);
	}
}
//非队列串口
//10ms调用一次
void uart_timing(void)
{
	if(mUart5.flag.rxstart){
		mUart5.rxotime++;
		if(mUart5.rxotime>=2){
			mUart5.rxotime=0;
			mUart5.flag.rxstart=0;
			mUart5.flag.rxstop=1;
		}
	}
}
//串口接收中断内调用
void uart_get_rx_data_it(u8 data)
{
	mUart5.rxotime=0;
	if(mUart5.flag.rxstart==0){
		mUart5.flag.rxstart=1;
		mUart5.rxlen=0;
	}
	if(mUart5.flag.rxstop==0){
		mUart5.rxbuf[mUart5.rxlen++]=data;
		if(mUart5.rxlen>=UART_RX_DATALEN-1)mUart5.rxlen=UART_RX_DATALEN-1;
	}
}

//队列相关
/*
获取队列缓冲剩余空间        接收缓冲由DMA循环填充，所以没有剩余空间的概念
n：串口号 0-3
*/
static u16 uart_tx_get_queue_idle_space(u8 n)
{
	u16 ret=0;
	if(mUart[n].tx_queue.buf_rear>mUart[n].tx_queue.buf_front)		ret=mUart[n].tx_queue.buf_rear-mUart[n].tx_queue.buf_front;
	else if(mUart[n].tx_queue.buf_rear<mUart[n].tx_queue.buf_front)
		ret=UART_TX_QBUFLEN-mUart[n].tx_queue.buf_front+mUart[n].tx_queue.buf_rear;
	else
		ret=UART_TX_QBUFLEN;
	return ret;
}

/*
获取队列当前队列数据数量
n：串口号 0-3
*/
u16 uart_tx_get_queue_data_num(u8 n)
{
	u16 ret=0;
	if(mUart[n].tx_queue.front>mUart[n].tx_queue.rear)
		ret=mUart[n].tx_queue.front-mUart[n].tx_queue.rear;
	else if(mUart[n].tx_queue.front<mUart[n].tx_queue.rear)
		ret=UART_TX_QUEUELEN-mUart[n].tx_queue.rear+mUart[n].tx_queue.front;
	else if(mUart[n].tx_queue.front==mUart[n].tx_queue.rear)
		ret=0;
	return ret;
}
u16 uart_rx_get_queue_data_num(u8 n)
{
	u16 ret=0;
	if(mUart[n].rx_queue.front>mUart[n].rx_queue.rear)
		ret=mUart[n].rx_queue.front-mUart[n].rx_queue.rear;
	else if(mUart[n].rx_queue.front<mUart[n].rx_queue.rear)
		ret=UART_RX_QUEUELEN-mUart[n].rx_queue.rear+mUart[n].rx_queue.front;
	else if(mUart[n].rx_queue.front==mUart[n].rx_queue.rear)
		ret=0;
	return ret;
}
/*
清空队列
n：串口号 0-3
*/
void uart_tx_clear_queue(u8 n)
{
	memset((void*)&mUart[n].tx_queue,0,sizeof(tx_queue_t));
}
void uart_rx_clear_queue(u8 n)
{
	memset((void*)&mUart[n].rx_queue,0,sizeof(rx_queue_t));
}
/*
写队列
n			串口号 0-3
buf			命令缓存指针
len			命令长度
*/
void uart_tx_write_to_queue(u8 n,u8 *buf,u16 len)
{
	u16 i;
	if(len<uart_tx_get_queue_idle_space(n)&&len<UART_TX_DATALEN){					//缓存有地方放，才写队列，否则直接扔掉
		if(mUart[n].tx_queue.rear==((mUart[n].tx_queue.front+1)%UART_TX_QUEUELEN)){	//队列数据数量满了，就覆盖掉最先写入的数据
			mUart[n].tx_queue.rear=(mUart[n].tx_queue.rear+1)%UART_TX_QUEUELEN;
			MY_LOG("覆盖一条数据");
		}
		//写入队列
		for(i=0;i<len;i++){
			mUart[n].txbuf[(mUart[n].tx_queue.buf_front+i)%UART_TX_QBUFLEN]=buf[i];
		}
		mUart[n].tx_queue.info_queue[mUart[n].tx_queue.front].len		=len;
		mUart[n].tx_queue.info_queue[mUart[n].tx_queue.front].addr		=mUart[n].tx_queue.buf_front;	//上一次的队列头等于这条数据的起始地址
		//队列头进一格
		mUart[n].tx_queue.buf_front=(mUart[n].tx_queue.buf_front+len)%UART_TX_QBUFLEN;					//这一条数据的结束地址是新的队列头
		mUart[n].tx_queue.front=(mUart[n].tx_queue.front+1)%UART_TX_QUEUELEN;	
	}	
	else{
		MY_LOG("发送缓存已满");
	}
}
//由idle中断调用
void uart_rx_write_to_queue(u8 n,u16 first,u16 last)
{
	if(mUart[n].rx_queue.rear==((mUart[n].rx_queue.front+1)%UART_RX_QUEUELEN)){	//队列数据数量满了，就覆盖掉最先写入的数据
		mUart[n].rx_queue.rear=(mUart[n].rx_queue.rear+1)%UART_RX_QUEUELEN;
		MY_LOG("覆盖一条数据");
	}
	//写入队列 数据区由DMA自动写入，仅需要将头尾地址写入队列即可
	mUart[n].rx_queue.info_queue[mUart[n].rx_queue.front].first		=first;
	mUart[n].rx_queue.info_queue[mUart[n].rx_queue.front].last		=last;	
	//队列头进一格
	mUart[n].rx_queue.front=(mUart[n].rx_queue.front+1)%UART_RX_QUEUELEN;	
}

//两个读队列函数，由串口任务调用
void uart_tx_read_from_queue(void)
{
	u8 n;
	u16 i;
	for(n=0;n<4;n++){
		if(mUart[n].tx_queue.flags.busy==0){			//发送完成才读下一条发送
			if(mUart[n].tx_queue.rear!=mUart[n].tx_queue.front){	//队列有数据
				if(mUart[n].get_tc==NULL||mUart[n].clear_tc==NULL)	continue;
				if(mUart[n].get_tc()==0)	continue;	//不能放在外面判断，否则会导致idle中断异常清空
				mUart[n].clear_tc();					//清除发送完成标志
				mUart[n].tx_queue.flags.busy=1;						//忙碌标志在DMA发送完成中断中清除
				mUart[n].tx_queue.info		=mUart[n].tx_queue.info_queue[mUart[n].tx_queue.rear];
				mUart[n].tx_queue.rear		=(mUart[n].tx_queue.rear+1)%UART_TX_QUEUELEN;		//队列尾追一格	
				mUart[n].tx_queue.buf_rear	=(mUart[n].tx_queue.buf_rear+mUart[n].tx_queue.info.len)%UART_TX_QBUFLEN;
			
				//取数据
				memset((void*)mUart[n].txdata,0,UART_TX_DATALEN);
				for(i=0;i<mUart[n].tx_queue.info.len;i++){
					mUart[n].txdata[i]=mUart[n].txbuf[(i+mUart[n].tx_queue.info.addr)%UART_TX_QBUFLEN];
				}
				//数据处理
				dma_uart_tx(n,mUart[n].tx_queue.info.len);	
			}
		}
	}
}
void uart_rx_read_from_queue(void)
{
	u8 n;
	u16 i;
	u16 len;
	for(n=0;n<4;n++){
		if(mUart[n].rx_queue.flags.busy==0){	//队列空闲
			if(mUart[n].rx_queue.rear!=mUart[n].rx_queue.front){	//队列有数据
				mUart[n].rx_queue.flags.busy=1;
				mUart[n].rx_queue.info		=mUart[n].rx_queue.info_queue[mUart[n].rx_queue.rear];
				mUart[n].rx_queue.rear		=(mUart[n].rx_queue.rear+1)%UART_RX_QUEUELEN;		//队列尾追一格	
				//取数据  如果需要做数据拼包，这里需要修改
				memset((void*)mUart[n].rxdata,0,UART_RX_DATALEN);
				if(mUart[n].rx_queue.info.first<mUart[n].rx_queue.info.last)	len=mUart[n].rx_queue.info.last-mUart[n].rx_queue.info.first;
				else len=UART_RX_QBUFLEN-mUart[n].rx_queue.info.first+mUart[n].rx_queue.info.last;
				if(len>UART_RX_DATALEN) return;
				for(i=0;i<len;i++){
					mUart[n].rxdata[i]=mUart[n].rxbuf[(i+mUart[n].rx_queue.info.first)%UART_RX_QBUFLEN];
				}
				//数据处理
				if(mUart[n].rxcallback!=NULL){
					mUart[n].rxcallback((u8*)mUart[n].rxdata,len);
				}
				//清除标志
				mUart[n].rx_queue.flags.busy=0;
			}
		}
	}
}

//放主循环
void Task_uart(void)
{
	uart_tx_read_from_queue();
	uart_rx_read_from_queue();
	if(mUart5.flag.rxstop){
		if(mUart5.rxcallback!=NULL){
			mUart5.rxcallback((u8*)mUart5.rxbuf,mUart5.rxlen);
		}
		mUart5.flag.rxstop=0;
	}
}




